package me.stone.stanimeclient.core.ui.adapters

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Typeface
import android.os.Build
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.LayoutParams
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import me.stone.stanimeclient.core.common.extensions.dip
import me.stone.stanimeclient.core.model.FilterTagData
import me.stone.stanimeclient.core.model.FilterTagItem
import me.stone.stanimeclient.core.ui.R
import me.stone.stanimeclient.core.ui.adapters.base.AbsSelectStateAdapter
import me.stone.stanimeclient.core.ui.adapters.holder.DefaultViewHolder
import me.stone.stanimeclient.core.ui.adapters.listener.OnItemSelectListener
import java.util.concurrent.Executor
import kotlin.math.roundToInt

class MultiTypeFiltersAdapter(
    private val backExecutor: Executor
): ListAdapter<FilterTagData, MultiTypeFiltersAdapter.HorizontalTagsHolder>(
    AsyncDifferConfig.Builder(DATA_DIFF_CALLBACK)
        .setBackgroundThreadExecutor(backExecutor)
        .build()
) {

    companion object {
        @JvmStatic
        private val DATA_DIFF_CALLBACK = object : DiffUtil.ItemCallback<FilterTagData>() {
            override fun areItemsTheSame(
                oldItem: FilterTagData,
                newItem: FilterTagData
            ): Boolean {
                return oldItem.typeValue == newItem.typeValue
            }

            override fun areContentsTheSame(
                oldItem: FilterTagData,
                newItem: FilterTagData
            ): Boolean {
                return oldItem == newItem
            }
        }

        @JvmStatic
        private val ITEM_DIFF_CALLBACK = object : DiffUtil.ItemCallback<FilterTagItem>() {
            override fun areItemsTheSame(
                oldItem: FilterTagItem,
                newItem: FilterTagItem
            ): Boolean {
                return oldItem.tagValue == newItem.typeValue
            }

            override fun areContentsTheSame(
                oldItem: FilterTagItem,
                newItem: FilterTagItem
            ): Boolean {
                return oldItem == newItem
            }
        }

        @JvmStatic
        private fun createRecyclerView(
            context: Context,
            viewPool: RecycledViewPool? = null
        ): RecyclerView {
            return RecyclerView(context).apply {
                layoutParams = ConstraintLayout.LayoutParams(
                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT
                )
                layoutManager = LinearLayoutManager(context).apply {
                    orientation = LinearLayoutManager.HORIZONTAL
                }
                itemAnimator = null
                viewPool?.let { setRecycledViewPool(viewPool) }
            }
        }

        @RequiresApi(Build.VERSION_CODES.M)
        @JvmStatic
        private fun createFilterTagView(context: Context): TextView {
            return TextView(context).apply {
                val dp4 = 4f.dip.roundToInt()
                val dp8 = 8f.dip.roundToInt()
                layoutParams = ConstraintLayout.LayoutParams(
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT
                ).apply {
                    setMargins(dp4, dp4, dp4, dp4)
                }
                setPaddingRelative(dp8, dp4, dp8, dp4)
                setTextColor(getStateColors(context))
                setBackgroundResource(R.drawable.shape_text_filter_tag)
            }
        }

        @RequiresApi(Build.VERSION_CODES.M)
        @JvmStatic
        private fun getStateColors(context: Context): ColorStateList {
            return context.getColorStateList(R.color.text_filter_tag)
        }
    }

    private inner class HorizontalTagsAdapter(
        backExecutor: Executor
    ): AbsSelectStateAdapter<FilterTagItem, DefaultViewHolder>(
        backExecutor = backExecutor,
        diffCallback = ITEM_DIFF_CALLBACK
    ) {

        @RequiresApi(Build.VERSION_CODES.M)
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DefaultViewHolder {
            return DefaultViewHolder(createFilterTagView(parent.context))
        }

        override fun bindViewData(holder: DefaultViewHolder, position: Int, item: FilterTagItem) {
            (holder.itemView as TextView).text = item.tagName
        }

        override fun onItemViewSelected(view: View) {
            (view as TextView).run {
                isSelected = true
                typeface = Typeface.DEFAULT_BOLD
            }
        }

        override fun onItemViewUnSelect(view: View) {
            (view as TextView).run {
                isSelected = false
                typeface = Typeface.DEFAULT
            }
        }

    }

    inner class HorizontalTagsHolder(recyclerView: RecyclerView): ViewHolder(recyclerView)

    var selectListener: OnItemSelectListener<FilterTagItem>? = null

    private val mItemSelectListener = object : OnItemSelectListener<FilterTagItem> {
        override fun onItemSelected(item: FilterTagItem) {
            selectListener?.onItemSelected(item)
        }

        override fun onItemUnselect(item: FilterTagItem) {
            selectListener?.onItemUnselect(item)
        }
    }

    private var mSelectedItems: Map<String, FilterTagItem> = emptyMap()

    private val mRecyclerPool = RecycledViewPool()

    fun updateSelectedItems(selectedItems: Map<String, FilterTagItem>) {
        mSelectedItems = selectedItems
        mSelectedItems.keys.mapNotNull { typeValue ->
            currentList.indexOfFirst { data -> data.typeValue == typeValue }.takeIf { it != -1 }
        }.forEach { position ->
            notifyItemChanged(position)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HorizontalTagsHolder {
        return HorizontalTagsHolder(createRecyclerView(parent.context, mRecyclerPool).apply {
            adapter = HorizontalTagsAdapter(backExecutor).also {
                it.itemSelectListener = mItemSelectListener
            }
        })
    }

    override fun onBindViewHolder(holder: HorizontalTagsHolder, position: Int) {
        val tagData = getItem(position)
        ((holder.itemView as RecyclerView).adapter as HorizontalTagsAdapter).also { adapter ->
            adapter.submitList(tagData.itemList)
            mSelectedItems[tagData.typeValue]?.let {
                item -> adapter.updateSelectedItem(item)
            }
        }
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        recyclerView.layoutManager = LinearLayoutManager(recyclerView.context).apply {
            orientation = LinearLayoutManager.VERTICAL
        }
        val dp4 = 4f.dip.roundToInt()
        recyclerView.setPaddingRelative(dp4, 0, dp4, 0)
    }

}